import CustomInput from '@/components/antd-comp/input/CustomInput'
import ThemeBtn from '@/components/antd-comp/theme-btn'
import { BlockEnum, WorkflowRunningStatus } from '@/components/workflow/types'
import { useWorkFlowStore } from '@/store/workflowStore'
import { matchVariablesToNodesV2 } from '@/util/utils'
import { Form, Input, InputNumber, Switch, Upload, message,Drawer } from 'antd'
import { Rule } from 'antd/es/form'
import { useEffect, useState } from 'react'
import { singleNodeRun } from '../../API'
import { useAutoSave } from '../../hooks/use-save'
import { findStartVariables } from '../../utils'
import { InboxOutlined } from '@ant-design/icons'
import { IconNumber1Small } from '@tabler/icons-react'
// import RowResult from './RunResult'

/**
 * 单节点试运行配置对象。
 *
 * @property {boolean} openDef - 是否开启单节点试运行功能，默认为 `false`。
 * @property {string}  title   - 显示的文案标题或标签，用于描述当前操作。
 * @property {string}  placement - 指定显示位置，可选值包括 'top', 'bottom', 'left', 'right' 等。
 * @property {boolean} setrunDrawerHid - 控制特定抽屉或面板的可见性，默认为 `false`。
 * @property {Object}  nodeData - 节点数据对象，包含与该节点相关的所有信息。
 */
export default function RunDrawer({ openDef, title = '试运行', placement = 'right', setrunDrawerHid, nodeData }: any) {
  const [form] = Form.useForm()
  const {
    clearRunInfo,
    setVerifying,
    flowVariables,
    singleRunningInfo,
    updateSingleRunningInfo,
    running,
    setRunning,
    flow,
    setFlowVariables,
    setDisabledEdit
  } = useWorkFlowStore()
  const [startVariables, setStartVariables] = useState({}) as any
  // 判断singleRunningInfo的key = data.id
  const hasMatchingId = Object.keys(singleRunningInfo).some(key => key === nodeData.id)
  const { autoSave } = useAutoSave()
  /* 重置runDrwaerHid */
  useEffect(() => {
    drawerClose()
  }, [])

  interface VariableInfo {
      id: string;
      variable: string;
      tempName: string;
      nodeId?: string;
      type?: string;
    }
  
  const processVariableReferences = (value: string): VariableInfo[] => {
    const matches = value.match(/\{\{([^}]+)\}\}/g) || []
    return matches.map(match => {
      const [nodeId, varName] = match.slice(2, -2).split(',')
      return {
        id: nodeId,
        variable: varName,
        tempName: `${nodeId}.${varName}`
      }
    })
  }
  
  const queryNodeUserInputVariables = (nodeData): VariableInfo[] => {
    const basicVars: VariableInfo[] = nodeData.inputList
      .filter(item => {
        return item.type === 'cite' 
        || (item.value && typeof item.value === 'string' && item.value.match(/\{\{.*?\}\}/))
      })
      .flatMap(item => {
        if (item.type === 'cite') {
          return [{
            id: item.value_selector[0],
            variable: item.value_selector[1],
            tempName: `${item.value_selector[0]}.${item.value_selector[1]}`
          }]
        } else {
          return processVariableReferences(item.value)
        }
      })
    
    if (nodeData.type === BlockEnum.HttpRequest) {
      // 处理 URL
      if (typeof nodeData.url === 'string' && nodeData.url.match(/\{\{.*?\}\}/)) {
        basicVars.push(...processVariableReferences(nodeData.url))
      }

      // 处理 headers
      if (Array.isArray(nodeData.headers)) {
        nodeData.headers.forEach(header => {
          if (typeof header.value === 'string' && header.value.match(/\{\{.*?\}\}/)) {
            basicVars.push(...processVariableReferences(header.value))
          }
        })
      }

      // 处理 params
      if (Array.isArray(nodeData.params)) {
        nodeData.params.forEach(param => {
          if (typeof param.value === 'string' && param.value.match(/\{\{.*?\}\}/)) {
            basicVars.push(...processVariableReferences(param.value))
          }
        })
      }
    }

    // 最后统一去重
    return Array.from(
      new Map(basicVars.map(item => [item.tempName, item])).values().filter(item => item.id !== undefined && item.variable !== undefined)
    )
  }


  useEffect(() => {
    const userInputVariables = queryNodeUserInputVariables(nodeData)
    const extractedVariables = matchVariablesToNodesV2(userInputVariables, flowVariables)
    setStartVariables({
      ...findStartVariables(flowVariables),
      variables: extractedVariables
    })

    setOpen(openDef)
    setRunning(false)
  }, [openDef])

  console.log('startVariables',startVariables)

  const [open, setOpen] = useState(true)

  const onClose = () => {
    drawerClose()
    setrunDrawerHid(false)
    setOpen(false)
  }

  const drawerClose = () => {
    setFlowVariables(nodeData.id, nodeData.title, { ...nodeData, runDrwaerHid: 0 })
  }
  // 保存版本
  const handleSaveEvent = async () => {
    await autoSave(flow.id)
  }

  const jsonfy = (obj: any) => {
    if (obj === null) {
      return ''
    }
    
    if (typeof obj === 'string') {
      return obj
    }else if (typeof obj === 'object') {
      try {
        return JSON.stringify(obj, null, 2)
      } catch (error) {
        console.error('Error parsing JSON:', error)
        return obj
      }
    } else {
      return obj
    }
  }
  /* 运行单节点 */
  const runSingleFun = async inputs => {
    const data = {
      workflow_id: flow.id,
      node_id: nodeData.id,
      inputs
    }
    try {
      setDisabledEdit(true)
      const res: any = await singleNodeRun(data)
      if (!res) return
      console.log('nodeData:', nodeData)

      // 根据运行时间秒数run_time  计算结束和开始时间
      const runTime = res?.run_time
      const endTime = new Date().valueOf()
      const startTime = runTime !== undefined && runTime >= 0 ? endTime - runTime * 1000 : endTime

      const singleRunningInfo = {
        inputs: res?.user_prompt,
        system_prompt: res?.system_prompt,
        outputs: res?.output?.output,
        startTime,
        endTime,
        // 多输出兼容参数
        outputsList: null
      }
      if (nodeData.type === BlockEnum.Code) {
        singleRunningInfo.inputs = JSON.stringify(res?.code_input, null, 2)
        singleRunningInfo.outputs = JSON.stringify(res?.code_output, null, 2)
      } else if (nodeData.type === BlockEnum.KnowledgeRetrieval) {
        singleRunningInfo.inputs = res?.input
      } else if (nodeData.type === BlockEnum.Intend) {
        const inputs = []
        for (const key in res?.input) {
          if (res?.input.hasOwnProperty(key)) {
            inputs.push({ variable: key, value: res?.input[key] })
          }
        }
        const list =
          res.id !== undefined && res.reason !== undefined
            ? {
                id: res.id,
                reason: res.reason
              }
            : []
        const outputsList = Object.entries(list).map(([variable, value]) => ({ variable, value }))
        singleRunningInfo.inputs = inputs && inputs.length > 0 ? inputs : null
        singleRunningInfo.outputsList = outputsList && outputsList.length > 0 ? outputsList : null
      } else if (nodeData.type === BlockEnum.HttpRequest) {
        singleRunningInfo.outputs = jsonfy(res.response)
      } else if (nodeData.type === BlockEnum.DocExtractor) {
        singleRunningInfo.outputs = jsonfy(res?.output?.output)
      }

      updateSingleRunningInfo(nodeData.id, WorkflowRunningStatus.Succeeded, singleRunningInfo)
      drawerClose()
    } catch (error) {
      console.log('runSingleFun catch:', error)
      updateSingleRunningInfo(nodeData.id, WorkflowRunningStatus.Failed)
    } finally {
      setDisabledEdit(false)
    }
  }

  const handleRunEvent = async () => {
    form
      .validateFields()
      .then(async values => {
        clearRunInfo()
        setVerifying(true)
        updateSingleRunningInfo(nodeData.id, WorkflowRunningStatus.Running)
        try {
          await handleSaveEvent()
          await runSingleFun(values)
        } catch (error) {
          /* 重置状态 */
          console.log(error)
          setVerifying(false)
          updateSingleRunningInfo(nodeData.id, WorkflowRunningStatus.Failed)
          drawerClose()
        }
      })
      .catch(err => {
        console.log('err', err)
      })
  }
  const [uploadProgress, setUploadProgress] = useState<Record<string, number>>({})
  const handleUpload = async (options: any) => {
    const { file, onSuccess, onError, onProgress } = options
    const formData = new FormData()
    
    formData.append('files', file)
    try {
      const response = await fetch('/api/v1/common/upload/batch', {
        method: 'POST',
        body: formData
      })

      if (response.ok) {
        const result = await response.json()
        onProgress({ percent: 100 }, file)
        onSuccess(result, file)
        return result.data[0]
      }
      throw new Error('上传失败')
    } catch (error) {
      message.error('文件上传失败')
      onError(error)
    }
  }
  return (
    <Drawer title={title} placement={placement} closable={false} onClose={onClose} open={open} getContainer={false}>
      <div className="flexCol ">
        {/* <span>试运行输入</span> */}
        <div className="mb-[100px]">
          <Form form={form} layout="vertical">
            {startVariables && startVariables?.variables?.length > 0 ? (
              startVariables.variables.map(item => {
                let inputNode
                const rules: Rule[] = [{ required: item.required, message: `${item.variable}不能为空` }]
                switch (item.type) {
                  case 'integer':
                    inputNode = (
                      <InputNumber
                        name={item.variable}
                        step={1}
                        precision={0}
                        min={-1000000000000}
                        placeholder="请输入"
                        max={1000000000000}
                        className="w-[80%]"
                      />
                    )
                    break
                  case 'number':
                    inputNode = (
                      <InputNumber
                        name={item.variable}
                        placeholder="请输入"
                        min={-1000000000000}
                        max={1000000000000}
                        className="w-[80%]"
                      />
                    )
                    break
                  case 'boolean':
                    inputNode = <Switch />
                    break
                  case 'file':
                    inputNode = (
                      <div className="upload-container" style={{ width: '400px' }}>
                        <Upload.Dragger
                          customRequest={handleUpload}
                          onChange={info => {
                            if (info.file.status === 'uploading') {
                              setUploadProgress(prev => ({
                                ...prev,
                                [item.variable]: info.file.percent || 0
                              }))
                            }
                            if (info.file.status === 'done') {
                              message.success(`${info.file.name} 上传成功`)
                              const fileUrls = info.fileList
                                .filter(file => file.status === 'done')
                                .map(file => file.response?.data[0])
                              form.setFieldValue(item.tempName, fileUrls)
                            } else if (info.file.status === 'error') {
                              message.error(`${info.file.name} 上传失败`)
                            }
                          }}
                          multiple={false}
                          showUploadList={true}
                          accept={".doc,.docx,.pdf,.ppt,.pptx,.txt,.jpg,.jpeg,.png,.xlsx,.md,.csv,.json,.log"}
                        >
                          <p className="ant-upload-drag-icon">
                            <InboxOutlined />
                          </p>
                          <p className="ant-upload-text text-sm">点击或将文件拖拽到这里上传</p>
                          <p className="ant-upload-hint text-gray-400 text-xs">
                            支持 DOC、DOCX、PDF、PPT、PPTX、TXT、XLSX、Markdown、CSV、JSON、LOG
                          </p>
                        </Upload.Dragger>
                        <div className="text-gray-400 text-xs mt-2">
                          注：文件支持UTF-8编码格式
                        </div>
                      </div>
                    )
                    break
                    case 'array_file':
                      inputNode = (
                        <div className="upload-container">
                          <Upload.Dragger
                            customRequest={handleUpload}
                            onChange={info => {
                              if (info.file.status === 'uploading') {
                                setUploadProgress(prev => ({
                                  ...prev,
                                  [item.variable]: info.file.percent || 0
                                }))
                              }
                              if (info.file.status === 'done') {
                                message.success(`${info.file.name} 上传成功`)
                                const fileUrls = info.fileList
                                  .filter(file => file.status === 'done')
                                  .map(file => file.response?.data[0])
                                form.setFieldValue(item.tempName, fileUrls)
                              } else if (info.file.status === 'error') {
                                message.error(`${info.file.name} 上传失败`)
                              }
                            }}
                            multiple={true}
                            showUploadList={true}
                            accept={".doc,.docx,.pdf,.ppt,.pptx,.txt,.jpg,.jpeg,.png,.xlsx,.md,.csv,.json,.log"}
                          >
                            <p className="ant-upload-drag-icon">
                              <InboxOutlined />
                            </p>
                            <p className="ant-upload-text text-sm">点击或将文件拖拽到这里上传</p>
                            <p className="ant-upload-hint text-gray-400 text-xs">
                              支持 DOC、DOCX、PDF、PPT、PPTX、TXT、XLSX、Markdown、CSV、JSON、LOG
                            </p>
                          </Upload.Dragger>
                          <div className="text-gray-400 text-xs mt-2">
                            注：文件支持UTF-8编码格式
                          </div>
                        </div>
                      )
                      break
                  case 'string':
                  case 'text':
                  default:
                    rules.push({ max: 1500, message: `输入不能大于1500个字符` })
                    inputNode = (
                      <CustomInput name={item.variable} autoComplete="off" placeholder="请输入" className="w-[80%]" />
                    )
                }

                return (
                  <Form.Item
                    key={item.id}
                    name={item.tempName}
                    label={`${item.variable}(${item.type})`}
                    required={item.required}
                    rules={rules}
                  >
                    {inputNode}
                  </Form.Item>
                )
              })
            ) : (
              <div className="flexRow flexCol">
                <svg
                  className="icon-icon icon-icon-coz_empty empty-icon--dprdk5FQwV45XsoH7WnE mb-[4px]"
                  width="32"
                  height="32"
                  viewBox="0 0 24 24"
                  fill="currentColor"
                  xmlns="http://www.w3.org/2000/svg"
                  style={{ color: 'rgba(55,67,106,0.38)' }}
                >
                  <path d="M11 5.5V2.5H13V5.5H11ZM7.207 3.293L9.207 5.293L7.793 6.707L5.793 4.707L7.207 3.293ZM18.207 4.707L16.207 6.707L14.793 5.293L16.793 3.293L18.207 4.707ZM5.347 8.992C5.52316 8.69012 5.77535 8.43967 6.07845 8.26562C6.38156 8.09157 6.72498 7.99998 7.0745 8H16.925C17.2746 8.00004 17.618 8.09169 17.9211 8.26584C18.2242 8.43998 18.4764 8.69053 18.6525 8.9925L21.7275 14.2625C21.906 14.5684 22 14.9163 22 15.2705V19.5C22 19.7626 21.9483 20.0227 21.8478 20.2654C21.7472 20.508 21.5999 20.7285 21.4142 20.9142C21.2285 21.0999 21.008 21.2472 20.7654 21.3478C20.5227 21.4483 20.2626 21.5 20 21.5H4C3.73736 21.5 3.47728 21.4483 3.23463 21.3478C2.99198 21.2472 2.7715 21.0999 2.58579 20.9142C2.40007 20.7285 2.25275 20.508 2.15224 20.2654C2.05173 20.0227 2 19.7626 2 19.5V15.27C2.00006 14.916 2.0941 14.5683 2.2725 14.2625L5.347 8.992ZM16.925 10H7.075L4.7415 14H10.7215L10.9465 14.675C10.9615 14.7131 10.9782 14.7504 10.9965 14.787C11.0415 14.877 11.1115 14.9955 11.2065 15.11C11.39 15.3305 11.6315 15.5 12.0005 15.5C12.3695 15.5 12.6105 15.3305 12.795 15.11C12.9024 14.9795 12.9897 14.8337 13.054 14.6775L13.0545 14.675L13.2795 14H19.2595L16.925 10ZM20 16H14.6135C14.5279 16.1361 14.4334 16.2664 14.3305 16.39C13.89 16.92 13.131 17.5 12 17.5C10.869 17.5 10.11 16.9195 9.6695 16.39C9.56662 16.2664 9.47208 16.1361 9.3865 16H4V19.5H20V16Z"></path>
                </svg>
                <span>本次试运行无需输入</span>
              </div>
            )}
          </Form>
          {/* 运行结果 */}
          {/* {(verifying || running) && hasMatchingId && <RowResult runInfo={singleRunningInfo[data.id]} />} */}
          {/* {resultType && (
            <RowResult
              runInfo={{
                inputs: nodeData.inputList,
                system_prompt: nodeData.callWord,
                outputs: nodeData.outputList
              }}
            />
          )} */}
        </div>
        {/* 运行按钮 */}
        <div className="absolute bottom-0 left-0 right-0 z-10 flex h-[56px] w-[100%] cursor-move items-center justify-center border-t-[0.5px] border-black/5 bg-[#ffffff]">
          <ThemeBtn loading={running} className="w-[80%]" onClick={() => handleRunEvent()}>
            试运行
          </ThemeBtn>
        </div>
      </div>
    </Drawer>
  )
}
